package com.hp.bon.sgw.threads;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;

public class TopN
{
  ConcurrentHashMap<String, UserStat> usrStatMap = new ConcurrentHashMap<String, UserStat>();
  private final int MAX_NUM_IN_QUEUE = 1000;
  private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");

  private int seq = 0;
  private int maxStatNum = 10;

	public int getMaxStatNum() {
		return maxStatNum;
	}
	public void setMaxStatNum(int maxStatNum) {
		this.maxStatNum = maxStatNum;
	}
	public void sort()
	{
		++seq;
		ArrayList<UserStat> all = new ArrayList<UserStat>(usrStatMap.values());
		int objectNum = all.size();
		long startTime,endTime;
		startTime = System.currentTimeMillis();
		for(UserStat o:all)
		{
			o.resetAndCalc();
		}
		endTime = System.currentTimeMillis();
		System.out.println("resetAndCalc,Object=" + objectNum + ",ms="+(endTime - startTime));
		startTime = System.currentTimeMillis();
		Collections.sort(all);
		endTime = System.currentTimeMillis();
		System.out.println("sort object=" + objectNum + ",ms="+(endTime - startTime));
		//�ҵ�����ǰ10�Ľ������
		for(int i = 0; i< 10 && i<all.size();++i)
		{
			System.out.println(all.get(i));
		}		
		
		//����MAX_NUM_IN_QUEUE֮��Ľ������
		startTime = System.currentTimeMillis();
		LinkedList<UserStat> deleteList = new LinkedList<UserStat>();
		for(int i =MAX_NUM_IN_QUEUE;i < all.size();++i)
		{
			deleteList.add(all.get(i));
		}
		for(UserStat deletO:deleteList)
		{
			if(deletO.curStat == null)
			{
				usrStatMap.remove(deletO.key);
			}
		}
		endTime = System.currentTimeMillis();
		System.out.println("remove object=" + deleteList.size() + ",ms="+(endTime - startTime));
	}
	//����ͳ�����
	public void addStat(String key,boolean falg)
	{
		UserStat userStat = usrStatMap.get(key);
		if(userStat == null)
		{
			userStat = new UserStat(key);
			usrStatMap.put(key, userStat);
		}
		userStat.add(falg);		
  }

  public static void main(String[] args)
  {
    long num = 1024L;
    System.out.print(num >> 2);

    TopN t = new TopN();
    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
      int j = (int)(Math.random() * 10000.0D);
      if (i % 33333 == 0) {
        try
        {
          Thread.sleep(50L);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      t.addStat(String.format("%1$06d", new Object[] { Integer.valueOf(j) }), true);
      if (i % 33333 == 0)
      {
        t.sort();
      }
    }
  }

  public class UserStat
    implements Comparable<UserStat>
  {
    String key;
    Stat curStat;
    int activeIndex;
    int counter;
    LinkedList<Stat> hisStat = new LinkedList<Stat>();

    public UserStat(String key2)
    {
      this.key = key2;
    }

    public int compareTo(UserStat o) {
      return o.activeIndex - this.activeIndex;
    }

    public void add(boolean falg)
    {
      if (this.curStat == null)
      {
        this.curStat = new Stat();
        this.curStat.timeSeq = TopN.this.seq;
        this.curStat.startDate = System.currentTimeMillis();
      }
      if (falg)
        this.curStat.successNum += 1;
      else
        this.curStat.errorNum += 1;
    }

    public void resetAndCalc()
    {
      int seqBase = TopN.this.seq - TopN.this.maxStatNum;
      if (this.hisStat.size() > 0)
      {
        Stat oldStat = (Stat)this.hisStat.getLast();

        if (oldStat.timeSeq <= seqBase)
        {
          this.hisStat.removeLast();
        }
      }
      if (this.curStat != null)
      {
        this.hisStat.addFirst(this.curStat);
        this.curStat = null;
      }
      if (this.hisStat.size() == 0)
      {
        this.activeIndex = -1;
        return;
      }

      this.counter = 0;
      this.activeIndex = 0;
      for (Stat stat : this.hisStat)
      {
        this.activeIndex += (stat.timeSeq - seqBase) * (stat.timeSeq - seqBase) * stat.successNum;
        this.counter += stat.successNum;
      }
    }

    public String toString()
    {
      if (this.hisStat.size() == 0)
      {
        return this.key + " not active";
      }
      return "key:" + this.key + ",Index:" + this.activeIndex + ",counter:" + this.counter + "," + this.hisStat;
    }

    public class Stat
    {
      long startDate;
      int successNum;
      int errorNum;
      int timeSeq;

      public Stat()
      {
      }

      public String toString()
      {
        return this.timeSeq + "-" + this.successNum;
      }
    }
  }
}